Custom Visual Example
function MyCustomVisual() {
this.onBeforeRender = function (api) {
};
this.importPaths = function () {
};
this.renderChunk = function (element, chunkData, api) {
var margin = 20;
var categoriesWidth = 80;
var height = api.size.height - margin * 2;
var width = api.size.width - margin * 2;
var d3 = api.deps.d3;
var dropZones = api.data.dropZones;
var colsData = api.data.groupBy(chunkData, dropZones.Columns);
var rowsData = api.data.groupBy(chunkData, dropZones.Rows);
var colsLength = Object.keys(colsData).length;
var rowsLength = Object.keys(rowsData).length;
var itemSizeWidth = (width - categoriesWidth) / colsLength;
var cellSizeWidth = itemSizeWidth - 1;
var itemSizeHeight = (height - categoriesWidth) / rowsLength;
var cellSizeHeight = itemSizeHeight - 1;
var xScale = d3.scale.scaleBand()
.domain(Object.keys(colsData))
.range([0, width - categoriesWidth]);
var yScale = d3.scale.scaleBand()
.domain(Object.keys(rowsData))
.range([0, height - categoriesWidth]);
var xAxis = d3.axis.axisTop(xScale);
var yAxis = d3.axis.axisLeft(yScale);
var yAxisSelection = d3.selection.select(element).selectAll('g.y-axis').data([null]);
yAxisSelection.exit().remove();
yAxisSelection = yAxisSelection
.enter()
.append('g')
.attr('class', 'y-axis')
.attr('transform', 'translate(95,100)')
.merge(yAxisSelection)
.call(yAxis);
var xAxisSelection = d3.selection.select(element).selectAll('g.x-axis').data([null]);
xAxisSelection.exit().remove();
xAxisSelection = xAxisSelection
.enter()
.append('g')
.attr('class', 'x-axis')
.attr('transform', 'translate(100, 95)')
.merge(xAxisSelection)
.call(xAxis)
.selectAll('text')
.attr("x", 8)
.attr("y", -2)
.attr("transform", "rotate(-65)")
.style("text-anchor", "start");
var fullData = [];
Object.keys(colsData).forEach(function (colData, i) {
var colDataPoints = colsData[colData].dataPoints;
colDataPoints.forEach(function (dp, j) {
var colName = api.data.getDataPointDropZoneCaption(dp, dropZones.Columns);
var rowName = api.data.getDataPointDropZoneCaption(dp, dropZones.Rows);
var value = api.data.getDataPointValue(dp);
fullData.push({
x: i,
y: j,
dataPoint: dp,
colName: colName,
rowName: rowName,
value: value
});
});
});
var groupSelection = d3.selection.select(element).selectAll('g.data').data([null]);
groupSelection.exit().remove();
groupSelection = groupSelection
.enter()
.append('g')
.attr('class', 'data')
.attr('transform', 'translate(100,100)')
.merge(groupSelection);
var rectSelection = d3.selection.select(element).select('g.data').selectAll('rect').data(fullData);
rectSelection.exit().remove();
rectSelection = rectSelection
.enter()
.append('rect')
.merge(rectSelection)
.attr('width', cellSizeWidth)
.attr('height', cellSizeHeight)
.attr('x', function (d) {
return d.x * itemSizeWidth;
})
.attr('y', function (d) {
return d.y * itemSizeHeight;
})
.attr('fill', function (d) {
return api.data.getColor(d.dataPoint, 'black');
})
.on('mouseover', function (d) {
api.interaction.showTooltip(d.dataPoint)
})
.on('mouseout', function (d) {
api.interaction.hideTooltip()
})
.on('contextmenu', function (d) {
api.interaction.showDatapointContextMenu(d.dataPoint, d3.selection.event);
})
.on("click", function (d) {
api.interaction.selectDatapoint(d.dataPoint, d3.selection.event)
});
}
this.onDataChanged = function (fullData, api) {
};
this.onThemeOrStyleChanged = function (api) {
};
this.getCustomStyle = function (api) {
var xAxisColor = api.style.styles.visuals.visualsXAxis.color;
var yAxisColor = api.style.styles.visuals.visualsYAxis.color;
var result = '.my-class {direction:rtl;}' +
'g.x-axis text {' +
'fill: ' + xAxisColor + ';}' +
'g.x-axis path, line {' +
'stroke: ' + xAxisColor + ';}' +
'g.y-axis text {' +
'fill: ' + yAxisColor + ';}' +
'g.y-axis path, line {' +
'stroke: ' + yAxisColor + ';}';
return result;
};
this.init = function () { };
}